;^Z80^
TITLE FILE: TAPE_MANA:TOS      HEWLETT-PACKARD: TAPE_MANAGER  (c) Coleco 1983 Confidential
;NAME ^Rev 6 - DTT^

DESCR_               MACRO
                       .GOTO ENDESCR_1

 Author:       DTT
 Project:      ________, ___
 Starting date:18feb83

 Prom release Date:
 Prom release Rev:

 Header Rev: 3

 ********************************
 *                              *
 *  TAPE_MANAGER    DTT         *
 *                              *
 ********************************

       Rev History (one line note indicating the change)

       Rev.  Date         Name      Change
        6    11/16/83  DTT       ADDED DEVICE ID TO SIMULATE DEVICE INDEPENDENCE
        5    12spt83   DTT       MODIFIED ERROR SYSTEM TO WRITE ERRORS TO CSA AREA
        4    08aug83   DTT       SIMULATES WRITES!
        3    07jul83   DTT       ADDED KILL_TAPE/CSA
        2    30jun83   DTT       STATE MACHINE FOR MULTI TASKING
        1    05apr83   DTT       BINK ON I/O ERROR, REMOVING TIMING STUFF, EI AND DI ADDED.
        0    10feb83   DTT       Initial Pseudo Code

 NAME: TAPE_MANAGER  (OVERLAY CONTROL)


 FUNCTION: (LOAD OVERLAYS VIA SIMULATED I/O WITH THE HP64000)


 INPUTS:   (ACCUMULATOR = OVERLAY NUMBER)


 OUTPUTS:  (OVERLAY IS LOADED TO RAM ADDRESS)


 PSEUDOCODE:  (PASCAL type pseudocode of procedure.)



         ----------------     overlay request? Y       ----------------
        :                :----------------------->    :                :
  :---->:    IDLE        :                            :    RENAME      :
  :     :                :                            :                :
  :     :                :---------:                  :                :
  :      ----------------          :                   ----------------
  :                /:\   overlay request? N                    :
  :                 :______________:                           :
  :                                                            :
  :                                                            :
  :                                                            :
  :                                                            :
  :                                                            :
  :                                                            :
  :                                                           \:/
  :      ----------------                              ----------------
  :     :                :                            :                :
  :     :    READ        : <--------------------------:      OPEN      :
  :     :    FIRST       :                            :                :
  :     :    RECORD      :                            :                :
  :      ------:---------                              ----------------
  :            :
  :            :
  :           \:/
  :      ----------------                              ----------------
  :     :                :------------------------>   :                :
  :     :    READ        :                            :    MOVE DATA   :
  :     :    DATA        :    end of file? N          :   FROM BUFFER  :
  :     :    RECORD      : <--------------------------:      TO RAM    :
  :      ----------------                              --------:-------
  :                                                            :
  :                                                      end of file? Y
  :                                                           \:/
  :      ----------------                              ----------------
  :     :                :                            :                :
   -----: PRE IDLE STATE :<---------------------------:      CLOSE     :
        :(WAIT FOR CLOSE):                            :                :
        :                :                            :                :
         ----------------                              ----------------
ENDESCR_1       MEND

DESC_a              MACRO
 .GOTO              DESC_a
 ***********************************************************************************************
  Each transition state looks like this:


   from previous
=================:
      state      :
                \:/
          ----------------:                      -----------------
         :                :  I/O errors? Y      :                 :
         : TRANSITION     :-------------------> :  ERROR STATE    :
    :===>:                :                     :  (terminate)    :----:
    :    :                :=====:               :                 :    :
    :     ----------------      :                ----------:------     :
    :            :              :                         /:\          :
    :            :              :                          :           :
    :  sim i/o   :             \:/                         :___________:
     ------------         ---------------- to state 6
       function          :                :============>
       complete? N       : TEST FOR       :
                         : ABORT          :to state 7
                         : REQUEST        :============>
                          ----------------
                           no   :
                         abort  : to next
                                : state
                               \:/

DESC_a          MEND

DESC_2          MACRO
 .GOTO          DESC_2
*
***************************************************************************************
*

    COMMON ATTRIBUTE AREAS (COMMUNICATION BUFFER WITH HP)
    ALL VALUES ARE HEXADECIMAL

    1) ASSIGN FILENAME TO CA
        CA      CA+1     CA+2             CA+n
     -------- -------- -------- -------- -------- -------- -------- --------
    :   8A   :LENGTH  :FILENAME ------> : USER ID         :  NOT
    :        :BYTE    :UP TO 9 BYTES    : UP TO 5 BYTES   :  USED----->
     -------- -------- -------- -------- -------- -------- -------- --------
     LENGTH_BYTE := (((((LENGTH OF FILE NAME)+1)/2)-1)*32) + ((LENGTH OF USER ID)/2)*8)
     FILENAME MUST BE ODD NUMBER OF BYTES LONG MAY BE PADDED WITH ONE SPACE.
     USER ID MUST BE EVEN NUMBER OF BYTES LONG MAY BE PADDED WITH ONE SPACE.

    2) OPEN
        CA      CA+1     CA+2
     -------- -------- -------- -------- -------- -------- -------- --------
    :   81   :   04   :   00   : NOT
    :        :        :        : USED------------------------------->
     -------- -------- -------- -------- -------- -------- -------- --------
     CA+1 MUST BE 04HEX DESIGNATES ABSOLUTE FILE WILL BE OPENED.
     CA+2 MUST BE 00HEX DESIGNATES DISK NUMBER.

    3) CLOSE
        CA
     -------- -------- -------- -------- -------- -------- -------- --------
    :   82   :  NOT
    :        :  USED ----------------------------------------------->
     -------- -------- -------- -------- -------- -------- -------- --------

    4) READ
        CA      CA+1     CA+2              CA+4              CA+6
     -------- -------- -------- -------- -------- -------- -------- --------
    :   87   :   80   : #BYTES TO LOAD  :  N/A   :  N/A   : LOAD ADDRESS
    :        :        :  MSB   :  LSB   :        :        :  MSB   :  LSB
     -------- -------- -------- -------- -------- -------- -------- --------
     CA+1 DEFINES THE BUFFER LENGTH IN WORDS - 1 MUST BE LOADED BEFORE CALLING SIM I/O
     CA+2 DEFINES NUMBER OF BYTES TO MOVE TO RAM FROM THE SIM I/O BUFFER
     CA+6 DEFINES THE RAM ADDRESS TO LOAD TO
     CA+8 (NOT SHOWN) IS THE START OF THE SIM I/O BUFFER
     NOTE: CA+2 AND CA+6 ARE ONE WORD LONG BUT NOT STORED AS Z80 WORDS.
           THE Z80 EXPECTS WORD VALUES TO BE STORED LSB/MSB.

DESC_2
       MEND



NEXT_STATE      MACRO LP1
         LD     A,LP1                          ;SOMETHING IN THE COMMAND BUFFER!
         LD     [TAPE_STATE],A
         LD     HL,[STATE_VECTORS+LP1+LP1]
         LD     [NEXT_STATE_ADDRESS],HL
         JP     END_OF_STATE_MACHINE
                MEND
;SUBROUTINES CALLED:
;      EXT

;OPERATING SYSTEM CALLS:

;EXTERNAL DATA AREAS USED:
                EXT KILL_TAPE
                EXT WRITE_TAPE
                EXT CSA
                EXT TAPE_STATE
                EXT OVERLAY_NUMBER

;GLOBAL DATA AREAS DEFINED:
         GLOBAL DEVICE_ID

;LOCAL EQUATES
CA       EQU    07400H                         ;COMMON ATTRIBUTES AREA FOR SIM I/O
BUF_LEN  EQU    CA+1
FILETYPE EQU    CA+1                           ;FILETYPE ADDRESS IN C_A_
DISC_NUM EQU    FILETYPE+1                     ;DISK NUMBER ADDRESS IN C_A_
REC_LEN  EQU    CA+2                           ;RECORD LENGTH ADDRESS IN C_A_
BUFFER   EQU    CA+8                           ;I_O_BUFFER
RNAM_BUF EQU    CA+1                           ;RENAME BUFFER AREA
LOADADDR EQU    CA+4                           ;ADDRESS OF MEM ADDRESS OF OVERLAY

MAXBUFLN EQU    128                            ;UP TO 128 WORDS MAY BE READ IN
ABSOLUTE EQU    004H                           ;FILE TYPE IS ABSOLUTE
OPEN     EQU    081H
CLOSE    EQU    082H
READ     EQU    087H
WRITE    EQU    089H
RENAME   EQU    08AH

;GLOBAL EQUATES
;      INCLUDE equate file name

 
       PROG
       GLOBAL   TAPE_MANAGER

       GLOBAL   INITIALIZE_TAPE
INITIALIZE_TAPE:
       GLOBAL   INIT_TAPE
INIT_TAPE:
         LD     A,0                            ;CLEAR THE HP64000 AREA
         LD     [CA],A
         LD     [CSA],A                        ;AND THE TAPE CONTROL STATUS AREA
         DEC    A
         LD     [OVERLAY_NUMBER],A             ;MAKE THE OVERLAY NUMBER -1 (INVALID)
         NEXT_STATE 0                          ;SET THE IDLE STATE!
         RET

TAPE_MANAGER:
;BEGIN        (Ordinarily registers are restored; retain only the pushes and pops you need.)

         LD     A,[CA]                         ;TEST THE STATUS OF THE FILE
         OR     A
         JP     M,END_OF_STATE_MACHINE         ;IF THERE IS A COMMAND IN THE BUFFER
         JR     Z,AB_REQ
         CP     1                              ;END OF FILE ON READ FROM HP64000
         JP     NZ,ERROR
;*
;*        AT THIS POINT ANY SIM I/O FUNCTIONS ARE COMPLETE; TEST FOR ABORTS (KILLS)
;*
         GLOBAL AB_REQ
AB_REQ:  LD     A,[CSA]                         ;IF COMMAND IS TO KILL TAPE COMMAND
         CP     KILL_TAPE
         JR     NZ,CASE_STATE
         LD     A,[TAPE_STATE]                  ;CHECK THE STATE OF THE TAPE
;*
         CP     3                               ;CHECK STATE 0,1,2
         JP     C,STATE_PRE_IDLE                ;FILE NOT OPENED
;*
         CP     6                               ;STATE 3,4,5
         JP     C,STATE_CLOSE                   ;FILE OPENED TRY TO CLOSE IT
;*
;*               FALL THRU TO CASE STATEMENT     ;IF STATE = 6,7
;*                                               ;FILE IS TRYING TO CLOSE
;*
;*
;*        CASE   TAPE_STATE,(IDLE,RENAME,OPEN,READ1,READ2,MOVE2VRAM,CLOSE,PRE_IDLE)
;*
CASE_STATE:
;*
;*
         LD     HL,[NEXT_STATE_ADDRESS]
         JP     [HL]
STATE_VECTORS:
         DEFW   STATE_IDLE                      ;STATE 0
         DEFW   STATE_RENAME                    ;      1
         DEFW   STATE_OPEN                      ;      2
         DEFW   STATE_READ_1                    ;      3
         DEFW   STATE_READ_2                    ;      4
         DEFW   STATE_MOVE2RAM                  ;      5
         DEFW   STATE_CLOSE                     ;      6
         DEFW   STATE_PRE_IDLE                  ;      7
         DEFW   WRITE_1
;*
;*        IF THE MACHINE IS IDLE IT'S OK TO TEST FOR ANOTHER READ REQUEST
;*
STATE_IDLE:                                     ;STATE 0
         LD     A,[CSA]                         ;TEST THE COMMAND STATUS AREA
         OR     A
         JP Z,END_OF_STATE_MACHINE
;*
         NEXT_STATE 1
;*
;*        ASSIGN THE SIM I/O FILE TO THE CURRENT OVERLAY NAME
;*
STATE_RENAME:                                   ;STATE 1
         LD     A,[OVERLAY_NUMBER]
         LD     HL,SAMPLE_NAME
         LD     DE,RNAM_BUF                     ;POINT TO THE RENAME BUFFER IN THE COMMON ATTRIBUTES AREA
         LD     BC,SAMPLE_NAME_LEN              ;NO NAME COULD BE MORE THAN TEN BYTES LONG COULD IT?
         LDIR                                   ;MOVE THE OVERLAY DATA TO THE RENAME BUFFER
;*
;*
;*
         LD     BC,10*256+"0"                   ;GET THE OVERLAY NUMBER INTO ASCII
OV_2_ASCII_1:
         OR     A
         SBC    A,B                             ;DIVIDE OVERLAY NUMBER BY 10
         INC    C                               ;SET THE NUMBER OF TENS IN C (DOESN'T RESET CARRY)
         JR     NC,OV_2_ASCII_1                 ;CARRY WAS SET BY SUBTRACT IF B>A
         DEC    C                               ;SAVE THE TENS BYTE
         ADD    A,B                             ;ADD TENS TO GET THE REMAINDER
         LD     B,"0"                           ;SAVE THE ONES BYTE
         ADD    A,B
         LD     B,A
         LD     A,C
         CP     "0"                             ;CONVERT TO ASCII
         JR     NZ,OV_2_ASCII_2
         LD     A,"_"                           ;SPECIAL CASE
OV_2_ASCII_2:
         LD     [DE],A                          ;DE IS POINTING TO THE FILENAME FROM THE LDIR ABOVE
         INC    DE
         LD     A,B
         LD     [DE],A
;*
;*        ASSIGN THE FILE
;*
         LD     A,RENAME
         LD     [CA],A
;*
         NEXT_STATE 2                           ;NEXT OPEN
;*
;*
STATE_OPEN:                                     ;STATE 2
;*
;*        OPEN THE FILE
;*
         LD     A,ABSOLUTE                      ;LOAD THE FILE TYPE
         LD     [FILETYPE],A
         LD     A,0                             ;DISK NUMBER
         LD     [DISC_NUM],A
         LD     A,OPEN                          ;OPEN THE CURRENT FILE
         LD     [CA],A
         LD     A,[CSA]                         ;NEXT STATE READ OR WRITE?
         NEXT_STATE 3                           ;NEXT STATE = READ_1
STATE_READ_1:                                   ;STATE 3
;*
;*        READ THE FIRST RECORD TO SKIP OVER IT
;*
         LD     A,MAXBUFLN                      ;SET THE INPUT BUFFER LENGTH
         LD     [BUF_LEN],A                     ;
         LD     A,READ
         LD     [CA],A                          ;READ THE FIRST RECORD

         NEXT_STATE 4

;*
;*        READ REMAINING RECORDS AND MOVE TO RAM
;*
STATE_READ_2:                                   ;STATE 4
         LD     A,MAXBUFLN                      ;SET THE INPUT BUFFER LENGTH
         LD     [BUF_LEN],A                     ;
         LD     A,READ                          ;
         LD     [CA],A

         NEXT_STATE 5                           ;NEXT STATE = READ A DATA RECORD

;*
;*        MOVE THE LAST BUFFER TO RAM
;*
STATE_MOVE2RAM:                                 ;STATE 5
         LD     A,[CA]                          ;CHECK THE RETURN STATUS
         OR     A
         JR     Z,NO_EOF                        ;END OF FILE?
;*
;*

         NEXT_STATE 6                           ;NEXT STATE = CLOSE FILE
NO_EOF:                                         ;MOVE THE CURRENT OVERLAY TO MEMORY
         LD     HL,[REC_LEN]                    ;GET THE NUMBER OF BYTES TO MOVE TO RAM
         LD     C,H
         LD     B,L
;*
         LD     HL,[LOADADDR]                   ;GET THE LOAD ADDRESS AND CHECK TO SEE IF IT IS IN VRAM
         LD     D,L
         LD     E,H
         LD     HL,BUFFER                       ;FROM ADDRESS

         LD     A,[CSA]
         CP     WRITE_TAPE
         JR     Z,WRITE_1

         LDIR
;*

         NEXT_STATE 4                           ;NEXT STATE = READ A DATA RECORD
;*
;*        CLOSE OVERLAY FILE
;*
STATE_CLOSE:                                    ;STATE 6
         LD     A,CLOSE                         ;CLOSE THE FILES
         LD     [CA],A

         NEXT_STATE 7                           ;NEXT STATE = PRE-IDLE
;*
;*
;*        NEXT STATE IS IDLE
;*
STATE_PRE_IDLE:                                 ;STATE 7
         LD     A,0                             ;NEXT STATE = PRE-IDLE
         LD     [CSA],A                         ;CLEAR THE COMMAND STATUS BUFFER
         DEC    A
         LD     [OVERLAY_NUMBER],A              ;SET THE OVERLAY NUMBER TO OUT OF RANGE
         NEXT_STATE 0
;*
;*        WRITE OUT 256 DATA BYTES TO AN OVERLAY! OH BOY!
;*
WRITE_1:                                        ;GET HERE FROM MOVE2RAM1
         EX     DE,HL
         LDIR
         LD     A,WRITE
         LD     [CA],A
         NEXT_STATE 6
;*
;*
;*

;  END (TAPE_MANAGER)

END_OF_STATE_MACHINE:
       XOR A
       RET
;***************************************************************************
;***************************************************************************
ERROR:
;  BEGIN       (Ordinarily registers are restored; retain only the pushes and pops you need.)

       LD C,A
       LD A,[OVERLAY_NUMBER]                    ;SAVE THE OVERLAY NUMBER IN A
       LD B,A
       LD A,[TAPE_STATE]
       LD HL,0                                  ;B HAS THE FUNCTION CODE
       LD [HL],A                                ;C HAS THE ERROR CODE
;
;   LD [HL] HAS JUST CAUSED A BINK TO OCCUR ON THE HP64000
;   THIS IS TO LET THE USER KNOW THERE HAS BEEN AN ERROR
;
       XOR     A
       LD      [CA],A                           ;CLEAR THE ERROR FROM THE HP64000
       INC     A                                ;PRETEND THE ERROR WAS A CRC CHECK FROM ADAM'S TAPE
       LD      [CSA],A
       LD      HL,[STATE_VECTORS+0000]
       LD      [NEXT_STATE_ADDRESS],HL
       RET

;  END (TAPE_ERR)

;***************************************************************************
;***************************************************************************
;
;   OVERLAY NAMES
;
;         -------- -------- -------- -------- --------
;        :LENGTH  :FILENAME ------> : USER ID         :
;        :BYTE    :UP TO 9 BYTES    : UP TO 5 BYTES   :
;         -------- -------- -------- -------- --------
;        LENGTH_BYTE := (((((LENGTH OF FILE NAME)+1)/2)-1)*32) + ((LENGTH OF USER ID)/2)*8)
;        FILENAME MUST BE ODD NUMBER OF BYTES LONG MAY BE PADDED WITH ONE SPACE.
;        USER ID MUST BE EVEN NUMBER OF BYTES LONG MAY BE PADDED WITH ONE SPACE.
;
;*****************************************************************************************
;*****************************************************************************************
;*
;*  OVERLAY NAME 0
;*
SAMPLE_NAME
OVLAY0   DEFB   FL_NM_LN0*32+US_ID_LN0*8        ;LENGTH DESCRIPTION BYTE
NAM_0    DEFB   "OVL_1"                         ;MUST BE ODD NUMBER OF LETTERS
USID0    DEFB   ""                              ;MUST BE EVEN NUMBER OF LETTERS
FL_NM_LN0 EQU   ((USID0-NAM_0+1)/2)-1           ;LENGTH OF FILENAME IN WORDS
US_ID_LN0 EQU   ($-USID0)/2                     ;LENGTH OF USERID IN WORDS
SAMPLE_NAME_LEN EQU $-SAMPLE_NAME-2             ;NUMBER OF BYTES TO MOVE = 4
;***********************************************************************
 DATA
 GLOBAL NEXT_STATE_ADDRESS
NEXT_STATE_ADDRESS DEFS 2                       ;POINTER TO NEXT ENTRY STATE
DEVICE_ID          DEFS 1                       ;DEVICE INDEPENDENCE SIMULATED